﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SqlClient;
using System.Data;

namespace MyKTVDao
{
    /// <summary>
    /// 获取数据库连接
    /// 1你要知道要去连接哪个数据库，该该数据库的账号密码是什么?
    /// 2我们如何从C#程序去连接一个sqlserver数据库服务器?
    /// 我们可以使用SQLconnection类封装了你从C#程序去连接一个数据库它所需要的所有的方法以及属性操作
    /// 3数据库连接有了，我们要从数据库中获取数据，相当于你有某个人的电话号码了，也有电话了，你需要联系某人就是去某人那里获取数据
    /// 你就要去打电话 所以我们的数据库连接就需要打开
    /// 4你需要将你的sql脚本传递给数据库让它去执行，负责数据库sql脚本操作的对象就是sqlcommand对象
    /// 它用来将你的数据库脚本传递给sqlserver数据库服务器去执行，并将返回值带给你。
    /// 5如果我们只需要做单值查询 就需要调用sqlcommand对象的scalar方法
    /// 如果我们需要做更新操作 那么就是 nonquery方法
    /// 如果我们是执行查询多值查询 那么就是 read方法
    /// 6数据库连接用完就需要关闭
    /// </summary>
   public class BaseDao
    {
      
        /// <summary>
        /// 数据库连接字符串
        /// </summary>
        private const string connStr = "Data Source=.;Initial Catalog=KTV;Integrated Security=True";



        /// <summary>
        /// 创建一个未打开的数据库连接对象并返回回去
        /// </summary>
        /// <returns>返回一个未打开的数据库连接对象</returns>
        protected SqlConnection CreateSqlConnection()
        {
            //使用数据库连接字符串 获取数据库连接对象
            SqlConnection conn = new SqlConnection(connStr);
            //返回数据库连接对象
            return conn;
        }
        /// <summary>
        /// 创建一个已经打开的数据库连接对象
        /// </summary>
        /// <returns>返回一个已经打开的数据库连接对象</returns>
        protected SqlConnection CreateOpenSqlConnection()
        {
            //直接调用之前写好的未打开的数据库连接对象方法 获得一个未打开的数据库连接对象
            SqlConnection conn = this.CreateSqlConnection();
            //将数据库连接打开
            conn.Open();
            //返回打开的数据库连接对象
            return conn;
        }

        /// <summary>
        /// 完成单值查询操作
        /// </summary>
        /// <param name="sql">sql脚本</param>
        /// <returns>返回查询结果</returns>
        public object DoScalar(string sql) {
            //获得一个打开的数据库连接
            using (SqlConnection conn=this.CreateOpenSqlConnection()) {
                //通过conn和sql脚本来获得sqlcommand对象
                SqlCommand command = new SqlCommand(sql,conn);
                //指定scalar方法 获得结果
              object obj=  command.ExecuteScalar();
                //返回结果
                return obj;
            }
        }

        public object DoScalar(string sql,SqlParameter[] paras)
        {
            //获得一个打开的数据库连接
            using (SqlConnection conn = this.CreateOpenSqlConnection())
            {
                //通过conn和sql脚本来获得sqlcommand对象
                SqlCommand command = new SqlCommand(sql, conn);
                //将我们需要添加的参数传递给command对象
                //由command对象来进行数据填充 而不是由我们来进行
                command.Parameters.AddRange(paras);
                //指定scalar方法 获得结果
                object obj = command.ExecuteScalar();
                //返回结果
                return obj;
            }
        }

        /// <summary>
        /// 使用命令化参数 放置sql注入
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="paras"></param>
        /// <returns></returns>
        public int DoNonQuery(string sql, SqlParameter[] paras) {
            //获得一个已经打开的数据库连接
            using (SqlConnection conn = CreateOpenSqlConnection())
            {
                //获得command对象
                SqlCommand command = new SqlCommand(sql, conn);
                //设置你需要填充替换的命令化参数
                command.Parameters.AddRange(paras);
                //返回执行结果
                return command.ExecuteNonQuery();
            }
        }

        /// <summary>
        /// 根据sql语句 查询结果集 使用datareader读书数据
        /// 
        /// </summary>
        /// <param name="cloumns">需要查询的列名</param>
        /// <param name="sql">需要执行的sql语句</param>
        /// <param name="param">你的参数</param>
        /// <returns>返回list集合</returns>
        public List<Dictionary<string, object>> DoDataReader(string[] cloumns,string sql,SqlParameter[] param) {
            List<Dictionary<string, object>> list = new List<Dictionary<string, object>>();
            //获得打开的数据库连接
            using (SqlConnection conn = this.CreateOpenSqlConnection())
            {
                //获得command对象
                SqlCommand command = new SqlCommand(sql,conn);
                //使用命令化参数防止sql注入
                command.Parameters.AddRange(param);
                //获得datareader对象
                //使用CommandBehavior.CloseConnection 让系统资管关闭reader对象
                SqlDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection);
                //使用datareader对象去去读取数据 存入dic字典中
                while (reader.Read()) {
                    //我们要根据我们传递过来的列名 来获取数据 存入字典中
                    Dictionary<string, object> dic = new Dictionary<string, object>();
                    foreach (string item in cloumns)
                    {
                        dic.Add(item, reader[item]);
                    }
                    //将字典添加到集合中
                    list.Add(dic);
                }
                //返回结果
                return list;
            }
        }
        /// <summary>
        /// 断开式数据库连接 无需打开数据库连接
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public DataTable GetDataTableBySql(string sql, SqlParameter[] param) {
            //1获得未打开的数据库连接对象
            using (SqlConnection conn = this.CreateSqlConnection())
            {
                //创建适配器对象
                SqlDataAdapter adapter = new SqlDataAdapter();
                //创建command对象
                SqlCommand command = new SqlCommand(sql,conn);
                //添加命令化参数 防止sql注入
                if (param != null)
                { 
                command.Parameters.AddRange(param);
                }
                //给适配器的查询执行命令对象赋值
                adapter.SelectCommand = command;
                //填充datatable
                DataTable table = new DataTable();
                //填充数据表
                adapter.Fill(table);
                //返回datatable
                return table;
            }
            //2创建dataadapter适配器
            //3填充datatble
            //4返回datatable
        }
    }
}
